// ==UserScript==
// @name         ops
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://ops.q7link.com:8080/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=q7link.com
// @grant        GM_setValue
// @grant        GM_xmlhttpRequest
// @grant        GM_notification
// @grant        GM_addElement
// @grant        GM_addStyle
// @require      https://unpkg.com/htm/preact/standalone.umd.js
// ==/UserScript==

(function () {
  "use strict";
  const {html, Component, render} = window.htmPreact
  const cookieObj = (function (cookieStr) {
    return cookieStr
      .split(";")
      .map((i) => i.trim())
      .reduce((acc, cur) => {
        const [k, v] = cur.split("=");
        acc[k] = v;
        return acc;
      }, {});
  })(document.cookie);

  // 通过部署的历史数据预测部署时间
  // 轮询监听目标环境的部署状态，发现开始部署则发通知
  // 环境 http://ops.q7link.com:8080/api/qqsystem/busenv/?page=1&limit=999
  // http://ops.q7link.com:8080/api/qqdeploy/jenkinsjob/?page=1&limit=20&queryJob=front-gen&parent_id=0
  // jenkins任务
  let navbar = document.querySelector(".navbar");
  if (navbar) {
    watch();
  } else {
    let loop = setInterval(() => {
      console.log("waiting navbar");
      navbar = document.querySelector(".navbar");
      if (navbar) {
        watch();
        clearInterval(loop);
      }
    }, 1000);
  }
  function watch() {
    console.log("navbar ready");
    GM_addStyle(`
    .opsContainer123 {
      display: inline-flex;
    }
    `);
    const n1 = document.querySelector(
      ".breadcrumb-container .el-breadcrumb__item:last-child .no-redirect"
    );
    console.log(n1.innerText);
    add(n1.innerText);
    const watchNode = document.querySelector(".breadcrumb-container>span");
    watchElement(watchNode, add);
  }

  function add(pageName) {
    const container = document.querySelector(".opsContainer123");
    if (container) {
      container.innerHTML = "";
      button(pageName);
      return;
    }
    const node = document.querySelector(".breadcrumb-container");
    const el = GM_addElement(node, "div", {
      textContent: new Date().toLocaleString() + "🤖",
    });
    el.classList.add("opsContainer123");

    button(pageName);
  }

  class DataSource extends Component {
    constructor(props) {
      super(props);
      this.state = { value: 0 };
    }

    render(props, state) {
      return html`
        <div class="row">
          <p>${this.state.value}</p>
          <button
            onClick=${(e) => this.setState({ value: this.state.value + 1 })}
          >
            add
          </button>
        </div>
      `;
    }
  }

  function button(pageName) {
    const bt = GM_addElement(
      document.querySelector(".opsContainer123"),
      "button",
      {
        textContent: "run!",
      }
    );
    bt.addEventListener("click", () => {
      // render(html`<${DataSource} />`, document.body);

      const table = document.querySelectorAll("table");
      console.log(table);
      table.forEach((i) => {
        const tr = i.querySelectorAll("tbody tr");
        tr.forEach((j) => {
          const rowData = j?.__vue__._props.row;
          const running = rowData.runStatus.toLowerCase() == "running";
          if (running) {
            const id = j.querySelector("td:first-child")?.innerText;
            const jobType = j.querySelector("td:nth-child(2)")?.innerText;
            console.log(id, jobType);
            GM_addElement(j.querySelector("td:first-child"), "button", {
              textContent: "❤️",
            }).addEventListener("click", () => {
              listenJenkinsJob(id, jobType);
            });
          }
        });
      });
    });
  }

  async function listenJenkinsJob(jobId, jobType) {
    const data = await getJenkinsJob(100, jobType);
    const job = data.find((i) => i.id == jobId);
    const avg = averageRun(data) | 0;
    const endTime = new Date(new Date(job.startTime).getTime() + avg);
    GM_notification({
      text: `平均运行${
        (avg / 60 / 1000) | 0
      }分钟，预计${endTime.toLocaleString()}结束。\n结束时会通知你，请不要关闭页面`,
      title: "开始监听任务运行状态",
    });
    const intervalId = setInterval(() => {
      if (new Date() > endTime) {
        // 开始查询运行结果
        getJenkinsJob(5, jobType).then((data) => {
          const job = data.find((i) => i.id == jobId);
          if (job.runStatus.toLowerCase() != "running") {
            // 如果运行成功或失败，则结束轮询并提示
            clearInterval(intervalId);
            GM_notification({
              text: `runStatus -> ${job.runStatus}`,
              title: "Jenkins Job is Finished",
            });
          }
        });
      }
    }, 10 * 1000);
  }

  function genResult() {
    // 
  }

  function averageRun(JenkinsJobs) {
    const jobs = JenkinsJobs.filter((i) => i.runStatus === "SUCCESS").map(
      (i) => ({
        start: new Date(i.startTime),
        end: new Date(i.endTime),
      })
    );
    const avgDuration =
      jobs.reduce((acc, cur) => {
        acc += cur.end - cur.start;
        return acc;
      }, 0) / jobs.length;

    return avgDuration;
  }
  function jenkinsUrl(limit, queryJob) {
    return `http://ops.q7link.com:8080/api/qqdeploy/jenkinsjob/?page=1&limit=${limit}&queryJob=${queryJob}&parent_id=0`;
  }
  function getJenkinsJob(limit, queryJob) {
    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: "GET",
        url: jenkinsUrl(limit, queryJob),
        headers: {
          "Content-Type": "application/json",
          Token: cookieObj.vue_admin_template_token,
        },
        onload: function (response) {
          const data = JSON.parse(response.responseText);
          resolve(data.data);
        },
      });
    });
  }

  function watchElement(targetNode, cb) {
    const observer = new MutationObserver((mutationList, observer) => {
      console.log("observer callback", observer, mutationList);
      for (const mutation of mutationList) {
        if (
          mutation.type === "childList" &&
          mutation.addedNodes.length > 0 &&
          mutation.addedNodes[0]?.innerText
        ) {
          const text = mutation.addedNodes[0].innerText;
          console.log("add -> " + text);
          switch (text) {
            case "Jenkins任务":
              debounce(cb, 1000)(text);
              break;

            default:
              break;
          }
        }
      }
    });
    observer.observe(targetNode, {
      attributes: false,
      childList: true,
      subtree: true,
    });
  }

  function debounce(func, timeout = 1000) {
    let timer;
    return (...args) => {
      clearTimeout(timer);
      timer = setTimeout(() => {
        func.apply(this, args);
      }, timeout);
    };
  }
})();
